//
// File:	Base.hpp
// Author:	Thomas TISSOT-DUPONT
// Login:	<thomas.tissotdupont@free.fr>
//
// Created:	25/04/2010 at 00:41:04
// Purpose:	
//
#ifndef BASE_HPP
#define BASE_HPP

#include <exception>
#include "IEngine.hpp"
#include "IConfig.hpp"
#include "IGlobal.hpp"
#include "IDisplayManager.hpp"
#include "IInputManager.hpp"
#include "IGuiManager.hpp"
#include "IEntityManager.hpp"
#include "IGameRuleManager.hpp"
#include "ISoundManager.hpp"
#include "IEventManager.hpp"
#include "IFactoryManager.hpp"
#include "Trace.hpp"

#define DECLARE_GLOBAL_VARIABLE(classname, name)		template <>																			\
														const std::string GlobalVariables::Template<classname>::Name() { return #name; }	\
														template class GlobalVariables::Template<classname>;								\
														typedef GlobalVariables::Template<classname> name

namespace GlobalVariables
{
	//------------------------------------------------------------------
	// Exception
	//------------------------------------------------------------------
	typedef std::exception		Exception;

	//------------------------------------------------------------------
	// Template
	//------------------------------------------------------------------
	template <typename T>
	class Template
	{
	public:
		static T					&Get() throw(...)
		{
			if (__instance == NULL)
				throw new Exception(("There is no instance found for: " + Template<T>::Name()).c_str());
			return *__instance;
		}
		static bool					Acquire(T *instance)
		{
			//Cannot acquire this variable twice
			if (!instance || __instance != NULL)
				return false;
			Template<T>::__instance = instance;
			return true;
		}
	private:
		static const std::string	Name()
		{
			return "<unknown>";
		}
	private:
		static T					*__instance;
	};
	template <typename T>
	T *Template<T>::__instance = NULL;

	//------------------------------------------------------------------
	// Global Variables
	//------------------------------------------------------------------
	DECLARE_GLOBAL_VARIABLE(IEngine,				Engine);
	DECLARE_GLOBAL_VARIABLE(IFactoryManager,		FactoryManager);
	DECLARE_GLOBAL_VARIABLE(IConfig,				Config);
	DECLARE_GLOBAL_VARIABLE(IGlobal,				Global);
	DECLARE_GLOBAL_VARIABLE(IDisplayManager,		DisplayManager);
	DECLARE_GLOBAL_VARIABLE(IInputManager,			InputManager);
	DECLARE_GLOBAL_VARIABLE(IGuiManager,			GuiManager);
	DECLARE_GLOBAL_VARIABLE(IEntityManager,			EntityManager);
	DECLARE_GLOBAL_VARIABLE(IGameRuleManager,		GameRuleManager);
	DECLARE_GLOBAL_VARIABLE(ISoundManager,			SoundManager);
	DECLARE_GLOBAL_VARIABLE(IEventManager,			EventManager);

	//------------------------------------------------------------------
	// Global Pointers structure for the SDK
	//------------------------------------------------------------------
	struct Pointers
	{
		IEngine					*engine;
		IFactoryManager			*factoryManager;
		IConfig					*config;
		IGlobal					*global;
		IDisplayManager			*displayManager;
		IInputManager			*inputManager;
		IGuiManager				*guiManager;
		IEntityManager			*entityManager;
		IGameRuleManager		*gameruleManager;
		ISoundManager			*soundManager;
		IEventManager			*eventManager;
	};
}

#endif //!BASE_HPP
